package hh.util.time;

import lombok.Data;

import java.io.Serializable;
import java.util.Date;
import java.util.TimeZone;


/**
 * Calender非线程安全，而且低效率
 *
 * @author huanghuai
 * @date 2020/9/30
 */
public abstract class MyCalender implements Serializable {

    private static final long serialVersionUID = 4773931905443347101L;
    public static final TimeZone TIME_ZONE = TimeZone.getDefault();


    private final int y = 1000;
    private final Year[] YEAR_ARR = new Year[y];
    private final Month[] MONTH_ARR = new Month[12];
    private final Month[] LEAP_MONTH_ARR = new Month[12];
    private final int[] MONTH_DAYS = {31, 28, 31, 30, 31, 30, 30, 31, 30, 31, 30, 31};

    {
        // 格林威治0ms = 1970-01-01 00:00:00.000 但是此时在中国，也是0ms但是因为时区问题是 1970-01-01 08:00:00.000
        //
        long msOffset = TimeUtil.parseDate("1970", TimeUtil.YYYY).getTime();
        int year = 1970;
        int totalDays = 0;
        for (int i = 0; i < y; i++) {
            Year y = new Year();
            y.leap = TimeUtil.isLeapYear(year);
            y.centuryLeap = TimeUtil.isCenturyLeapYear(year);
            y.year = year;
            y.totalDaysOfThisYear = y.leap ? TimeUtil.LEAP_YEAR_DAYS : TimeUtil.ORDINARY_YEAR_DAYS;
            y.millisecondsOfThisYear = y.totalDaysOfThisYear * TimeUtil.DAY_MS + msOffset;
            y.totalDays = totalDays;
            y.totalMillisecond = totalDays * TimeUtil.DAY_MS;

            YEAR_ARR[i] = y;
            totalDays += y.totalDaysOfThisYear;
            year++;
        }
        totalDays = 0;
        int leapMonthTotalDay = 0;
        for (int i = 0; i < MONTH_ARR.length; i++) {
            Month month = new Month();
            int totalDaysOfThisMonth = MONTH_DAYS[i];
            month.setTotalDaysOfThisMonth(totalDaysOfThisMonth);
            month.setMonth(i + 1);
            month.setTotalDays(totalDays);
            month.setTotalMillisecondOfThisMonth(month.getTotalDaysOfThisMonth() * TimeUtil.DAY_MS);
            MONTH_ARR[i] = month;

            Month leapMonth = new Month();
            if (i == 1) {
                totalDaysOfThisMonth += 1;
            }

            leapMonth.setTotalDays(leapMonthTotalDay);
            leapMonth.setTotalDaysOfThisMonth(totalDaysOfThisMonth);
            leapMonth.setMonth(i + 1);
            leapMonth.setTotalMillisecondOfThisMonth(month.getTotalDaysOfThisMonth() * TimeUtil.DAY_MS);
            LEAP_MONTH_ARR[i] = leapMonth;
            totalDays += month.totalDaysOfThisMonth;
            leapMonthTotalDay += leapMonth.totalDaysOfThisMonth;

        }

    }

    /**
     * 从1970年开始闰年数量小于365，这个方法是对的 <br>
     * 1972是闰年，365*3=1095天不属于1973而是1972，1096天才是1973
     *
     * @return
     */
    protected Year getYear(long ms) {
        int d = (int) (ms / TimeUtil.DAY_MS);
        int idx = d / TimeUtil.ORDINARY_YEAR_DAYS;
        Year year = YEAR_ARR[idx];
        if (year.totalDays > d) {
            idx = idx - 1;
        }
        return YEAR_ARR[idx];
    }

    protected Month getMonth(boolean leap, long monthMs) {
        Month[] monthArr = leap ? LEAP_MONTH_ARR : MONTH_ARR;
        int days = (int) (monthMs / TimeUtil.DAY_MS);
        int idx = (days / 28);
        if (monthArr[idx].totalDays > days) {
            idx--;
        }
        return monthArr[idx];
    }

    protected Day getDay(long dayMs) {
        return null;
    }

    public int year(Date date) {
        return year(date == null ? System.currentTimeMillis() : date.getTime());
    }

    public int year(long ms) {
        return getYear(ms).year;
    }

    public String yearMonth(long ms) {
        Year year = getYear(ms);
        Month month = getMonth(year.isLeap(), ms - year.totalMillisecond);
        return year.year + "-" + month.month;
    }

    public String yearMonthDay(long ms) {
        Year year = getYear(ms);
        Month month = getMonth(year.isLeap(), ms - year.totalMillisecond);
        Day day = getDay(ms - year.totalMillisecond);
        return year.year + "-" + month.month + "-" + day;
    }


    public String yearMonth(Date date) {
        return yearMonth(date == null ? System.currentTimeMillis() : date.getTime());
    }


    /**
     * 代表某一年的1月1日 0点0分0秒0毫秒, 就是某一年的最开始时间
     */
    @Data
     static class Year implements Cloneable {

        public Year(Year y) {
            this.year = y.year;
            this.totalDaysOfThisYear = y.totalDaysOfThisYear;
            this.millisecondsOfThisYear = y.millisecondsOfThisYear;
            this.leap = y.leap;
            this.centuryLeap = y.centuryLeap;
            this.totalDays = y.totalDays;
            this.totalMillisecond = y.totalMillisecond;
        }

        @Override
        public Year clone() {
            return new Year(this);
        }

        public Year() {
        }


        /**
         * eg：2020 年
         */
        private int year;
        /**
         * 这一年有多少天
         */
        private int totalDaysOfThisYear;

        /**
         * total毫秒值
         */
        private long millisecondsOfThisYear;
        /**
         * 是否闰年
         */
        private boolean leap;
        /**
         * 是否世纪闰年
         */
        private boolean centuryLeap;
        /**
         * 从1970到这一年，共经历多少天
         */
        private int totalDays;
        /**
         * total毫秒值
         */
        private long totalMillisecond;

        @Override
        public String toString() {
            return "Year{" +
                    "year=" + year +
                    ", daysOfThisYear=" + totalDaysOfThisYear +
                    ", millisecondsOfThisYear=" + millisecondsOfThisYear +
                    ", leap=" + leap +
                    ", centuryLeap=" + centuryLeap +
                    ", totalDays=" + totalDays +
                    ", totalMillisecond=" + totalMillisecond +
                    '}';
        }
    }

    /**
     * 代表某一年的某一个月的1号 0点0分0秒0毫秒, 就是某一月的最开始时间
     */
    @Data
     static class Month implements Cloneable {
        private Year year;

        public Month(Year year, int totalDaysOfThisMonth, int totalDays, int month, long totalMillisecondOfThisMonth) {
            this.year = year;
            this.totalDaysOfThisMonth = totalDaysOfThisMonth;
            this.totalDays = totalDays;
            this.month = month;
            this.totalMillisecondOfThisMonth = totalMillisecondOfThisMonth;
        }

        public Month() {
        }

        @Override
        public Month clone() {
            return new Month(year, totalDaysOfThisMonth, totalDays, month, totalMillisecondOfThisMonth);
        }

        /**
         * 一个月几天
         */
        private int totalDaysOfThisMonth;
        /**
         * 从一月1号到这个月1月1号，共经历多少天
         */
        private int totalDays;
        /**
         * 第几月
         */
        private int month;
        /**
         * total毫秒值
         */
        private long totalMillisecondOfThisMonth;
    }

    /**
     * 代表某一年的某一个月的某一天的 时间
     */
    @Data
    static class Day {
        private Month month;
        private int hour;
        private int minute;
        private int second;
        private int millisecond;
        private int weekNumber;
        /**
         * 这个月的第几天
         */
        private int dayOfThisMonth;
        /**
         * 这一年是第几天
         */
        private int dayOfThisYear;
    }
}
